ContentfulのUI ExtensionでエディタをWYSIWYGにカスタマイズしてみる
ベルリンオフィスの小西です。
ヘッドレスCMSのContentfulではUI Extensionという拡張機能を使ってエディタやダッシュボードのカスタマイズが可能です。使いこなせればヘッドレスCMSで課題になるエディタ周りの柔軟性をカバーできます。
今回はUI Extensionの作成を通じてContentfulデフォルトのマークダウン式テキストエディタをAlloy Editorに置き換えてみます。
Alloy Editorとは
Alloy EditorはオープンソースのWYSIWYGなエディタです。
エディタ上での画像のドラッグ&ドロップ、スタイルの適用などが可能になり、マークダウンに慣れ親しんでいない人にとって直感的なエディタを提供できます。
前提
※本記事はContentfulをある程度利用されている方を想定しています。
UI Extensionを実装するにはソースコードをContentfulに読み込ませる必要があります。
ソースコードはGithubかローカルでホストする必要があり、今回はローカルでホストしてContentfulに読み込ませる形を取ります。
実装に先立って下記のインストールが必要になります。
- npm
- Contentful CLI (参考記事)
早速実装してみる
ローカルでUI Extensionのアプリケーションを作成します。
% npx @contentful/create-contentful-extension alloy-editor-sample npx: installed 47 in 9.615s Creating a new Contentful extension in /Users/ryokonishi/Dev/alloy-editor-sample. ? Select type of extension: (Use arrow keys) ❯ Field extension Sidebar extension Entry editor extension Page extension
-> Field extension
を選択します。
UI ExtensionはContentfulダッシュボード上での表示箇所を選ぶことができます。今回はエディタのフィールドを置き換えたいので、Field extension
を選択します。
? Select field types for this extension: ◯ Assets ◯ Symbol ◯ Symbols ❯◉ Text ◯ RichText ◯ Integer ◯ Number
-> Text
を選択します。
ちなみにちょっとわかりにくいのが、このText
はContentfulダッシュボードでいう[Text / Long text]フィールドを指します。[Short Text]に対してExtensionを作成したい場合はSymbol
を選択します。
? What language you want to use to develop extension: (Use arrow keys) ❯ JavaScript TypeScript
-> JavaScript
を選択。
インストールが始まります。
Success! Created alloy-editor-sample at /Users/ryokonishi/Dev/alloy-editor-sample
成功したらアプリケーションディレクトリに移動し、依存パッケージをインストールします。
% cd alloy-editor-sample
% npm install
次に、CLIからContentfulにログインします。
ブラウザが開き、CMA(Content Management API = コンテンツをContntfulに対してPostするトークン)をコピーして、CLIに貼り付けます。
% npm run login > alloy-editor-sample@0.1.0 login /Users/ryokonishi/Dev/alloy-editor-sample > contentful login A browser window will open where you will log in (or sign up if you don’t have an account), authorize this CLI tool and paste your CMA token here: ? Open a browser window now? Yes ? Paste your token here: [hidden] Great! Your CMA token is now stored on your system. (Located at /Users/ryokonishi/Dev/alloy-editor-sample/.contentfulrc.json) You can always run contentful logout to remove it.
次に、どのContentfulのSpaceに連携するか設定します。
% npm run configure > alloy-editor-sample@0.1.0 configure /Users/ryokonishi/Dev/alloy-editor-sample > contentful space use && contentful space environment use ? Please select a space: space_name (XXXXXXXX) Now using the 'master' Environment of Space bq (hgb7pexouhv0) when the `--environment-id` option is missing. ? Please select an environment: master (master) Now using Environment master (master) in Space bq (hgb7pexouhv0) when the `--environment-id` option is missing.
準備が完了したので、アプリを素の状態で立ち上げてみます。
% npm run start > alloy-editor-sample@0.1.0 start /Users/ryokonishi/Dev/alloy-editor-sample > contentful-extension-scripts start Installing extension in development mode... ✨ Successfully created extension: Space: XXXXXXXX Environment: master Your extension: https://app.contentful.com/spaces/XXXXXXXX/settings/extensions/alloy-editor-sample ┌───────────────────────────────┬───────────────────────┐ │ Property │ Value │ ├───────────────────────────────┼───────────────────────┤ │ ID │ alloy-editor-sample │ ├───────────────────────────────┼───────────────────────┤ │ Name │ alloy-editor-sample │ ├───────────────────────────────┼───────────────────────┤ │ Field types │ Text │ ├───────────────────────────────┼───────────────────────┤ │ Src │ http://localhost:1234 │ ├───────────────────────────────┼───────────────────────┤ │ Version │ 1 │ ├───────────────────────────────┼───────────────────────┤ │ Parameter definitions │ Instance: 0 │ │ │ Installation: 0 │ ├───────────────────────────────┼───────────────────────┤ │ Installation parameter values │ 0 │ └───────────────────────────────┴───────────────────────┘
これでローカル( http://localhost:1234 )でUI Extensionアプリがホストされた状態になり、かつ連携したContentfulのSpaceにもアプリがデプロイされました。
ちなみにcreate-contentful-extensionの各コマンドはこんな感じ。
npm run start
Developmentサーバーを立ち上げて開発モードでExtensionをデプロイします。
一度立ち上げると変更が自動的に反映されます。
npm run login
CLIツールにContentfulアカウントでログイン。作業に必要なCMA(コンテンツマネージメントAPI)が発行される。
npm run logout
CLIツールのセッションを切る。
npm run configure
ContentfulのSpaceとEnvironmentの設定。内容は.contentfulrc.json
に保存される。これはリポジトリに上げてはいけない。
npm run build
Extensionをビルドして/build
フォルダにまとめる。依存関係をバンドルして最適化。デプロイは各自自由にやってねというスタンス。
デプロイされたUI Extensionを確認してみる
https://app.contentful.com/spaces/hgb7pexouhv0/settings/にアクセスすると、[alloy-editor-sample]という名前のUI Extensionが追加されてるのが確認できるはずです。
詳細ページでは下記が確認できます。
- [Field types]として
Text
が選択されている - [Self-hosted]として
http://localhost:1234
が指定されている
それではローカルでアプリの中身を変更していきます。
{ "id": "alloy", "name": "Alloy Text Editor", "srcdoc": "./index.html", "fieldTypes": ["Text"] }
<!DOCTYPE html> <head> <link href="https://contentful.github.io/ui-extensions-sdk/cf-extension.css" rel="stylesheet"> <link href="https://contentful.github.io/extensions/libs/alloy-editor/assets/alloy-editor-ocean-min.css" rel="stylesheet"> <script src="https://contentful.github.io/extensions/libs/alloy-editor/alloy-editor-all-min.js"></script> <script src="https://unpkg.com/contentful-ui-extensions-sdk@3"></script> <style> body { margin: 0; border: 1px solid #ccc; border-radius: 4px; overflow: hidden; } #content { outline: 0; padding: 1em; margin-left: 3em; margin-top: -1px; margin-bottom: -1px; min-height: 30em; } </style> </head> <body> <div id="content"></div> <script> var cfExt = window.contentfulExtension || window.contentfulWidget const AlloyEditor = window.AlloyEditor cfExt.init(function (ext) { var currentValue ext.window.startAutoResizer() const editor = AlloyEditor.editable('content')._editor editor.setData(ext.field.getValue()) ext.field.onValueChanged(function(value) { if (value !== currentValue) { currentValue = value editor.setData(value) } }) editor.on('change', function() { const value = editor.getData() if (currentValue !== value) { currentValue = value ext.field.setValue(value) } }) }) </script> </body>
再度アプリを立ち上げます。
% npm run start
Contentful側にも再度リロードされ、アプリの準備は完了です。
Contentful側の設定
Content Modelがすでに作成されてる前提で、新しいフィールドを追加していきます。
[Add new field]からフィールドタイプで[Text]を選択
[Appearance]から、先ほど作成した[alloy-editor-sample]が表示されているので選択
以上のフィールドを追加完了したら、新規投稿ページに遷移。
投稿フィールドを見てみると、Alloy Editorが適用されたエディタになっています。
Done!
さいごに
ContentfulにはAppsというより広範なカスタマイズを可能にする拡張機能もあります。今後統合されていきそうな気配ですが、今回はフィールド単位のカスタマイズだったのでUI Extensionsを使ってサクッと実装してみました。
参考URL
https://github.com/contentful/contentful-cli
https://www.contentful.com/developers/docs/extensibility/ui-extensions/